#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

#include <sys/ioctl.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>

#include "ioctl_timer.h"

#define DEV_NAME        "/dev/ioctl_timer_dev"

#define DATA_NUM        (32)
#define ALIGNMENT_BITS        (64)
#define GET_SMALL_ALIGNMENT_VAL(x, y)        ((x)  & ~(y-1))
#define GET_BIG_ALIGNMENT_VAL(x, y)        (((x)  & ~(y-1)) + (y))  //0==x%y
static void show_uint8_content(uint8_t *data, uint32_t size);
int fd = -1;
int ret = -1;
uint8_t *data = NULL;
uint32_t size = 0;
void signal_handler(int signo, siginfo_t *info, void *extra) {
    int ret = 0;
    printf("[%s +%d %s] +++++++++++++++++= size=%d\n", __FILE__, __LINE__, __func__, size);
    ret = read(fd, data, size);
    if (0 != ret)
    {
        printf("[%s +%d %s] ioctl(TLS_AUDIO_IOCTL_READ) failed\n", __FILE__, __LINE__, __func__);
    }
    show_uint8_content(data, 8);

}
int main(void)
{
    CONFIG_T config;
    uint8_t *writeData = NULL;
    uint32_t read_run_cnt = 0;
    
    struct sigaction action;
    action.sa_flags = SA_SIGINFO;
    action.sa_sigaction = signal_handler;

     printf("[%s +%d %s] start\n", __FILE__, __LINE__, __func__);

    if (-1 == sigaction(44, &action, NULL)) {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }
    
    config.pid = getpid();
    #if 0
    config.size = 1025;
    printf("[%s +%d %s] GET_SMALL_ALIGNMENT_VAL(config.size, ALIGNMENT_BITS)=%d\n", __FILE__, __LINE__, __func__, GET_SMALL_ALIGNMENT_VAL(config.size, ALIGNMENT_BITS));

    printf("[%s +%d %s] GET_BIG_ALIGNMENT_VAL(config.size, ALIGNMENT_BITS)=%d\n", __FILE__, __LINE__, __func__, GET_BIG_ALIGNMENT_VAL(config.size, ALIGNMENT_BITS));
    config.size = 2048;
    printf("[%s +%d %s] GET_SMALL_ALIGNMENT_VAL(config.size, ALIGNMENT_BITS)=%d\n", __FILE__, __LINE__, __func__, GET_SMALL_ALIGNMENT_VAL(config.size, ALIGNMENT_BITS));
    printf("[%s +%d %s] GET_BIG_ALIGNMENT_VAL(config.size, ALIGNMENT_BITS)=%d\n", __FILE__, __LINE__, __func__, GET_BIG_ALIGNMENT_VAL(config.size, ALIGNMENT_BITS));

    #endif
    config.size = (48000 * 24 * 2) / 8 / 1000 * 20; //20ms bytes
    if(0 != (config.size % ALIGNMENT_BITS))
    {
        printf("[%s +%d %s] WARING config.size ALIGNMENT_BITS(%d) != 0\n", __FILE__, __LINE__, __func__, ALIGNMENT_BITS);
    }
    size = config.size;
    printf("[%s +%d %s] config.pid=%d config.size=%d\n", __FILE__, __LINE__, __func__, config.pid, config.size);
    data = (uint8_t *)malloc(config.size * sizeof(uint8_t));
    if(NULL == data)
    {
        printf("[%s +%d %s] malloc(%ld) failed\n", __FILE__, __LINE__, __func__, config.size * sizeof(uint8_t));
		goto err_malloc;
    }
    writeData = (uint8_t *)malloc(config.size * sizeof(uint8_t));
    if(NULL == writeData)
    {
        printf("[%s +%d %s] writeData malloc(%ld) failed\n", __FILE__, __LINE__, __func__, config.size * sizeof(uint8_t));
		goto err_malloc_writeData;
    }

    for(int i = 0; i < config.size; i++)
    {
        data[i] = i;
    }
    show_uint8_content(data, 8);
    printf("[%s +%d %s] open(%s)\n", __FILE__, __LINE__, __func__, DEV_NAME);
    fd = open(DEV_NAME, O_RDWR);
    if (-1 == fd)
    {
        printf("[%s +%d %s] open(%s) failed\n", __FILE__, __LINE__, __func__, DEV_NAME);
		goto err_open;
    }
    else
    {
        printf("[%s +%d %s] open success\n", __FILE__, __LINE__, __func__);
	}

    ret = ioctl(fd, TLS_AUDIO_IOCTL_INIT_ASYNC_READ, &config);
    if (0 != ret)
    {
        printf("[%s +%d %s] ioctl(TLS_AUDIO_IOCTL_INIT_READ) failed\n", __FILE__, __LINE__, __func__);
        goto err_ioctl_TLS_AUDIO_IOCTL_INIT_READ_failed;
    }
    read_run_cnt = 0;
    while(1)
    {
        if(0 == ((read_run_cnt + 1) % 2))
        {
            for(int i = 0; i < config.size; i++)
            {
                writeData[i] = read_run_cnt + 100;
            }
            ret = write(fd, writeData, config.size);
            if (0 != ret)
            {
                printf("[%s +%d %s] ioctl(TLS_AUDIO_IOCTL_INIT_READ) failed\n", __FILE__, __LINE__, __func__);
                goto err_ioctl_TLS_AUDIO_IOCTL_INIT_READ_failed;
            } 
        }
        if(20 < read_run_cnt)
        {
            break;
        }
        sleep(2);
        read_run_cnt ++;
        printf("[%s +%d %s] read_run_cnt=%d\n", __FILE__, __LINE__, __func__, read_run_cnt);

    }
err_ioctl_TLS_AUDIO_IOCTL_INIT_READ_failed:
    if (-1 != fd)
    {
        close(fd);
        fd = -1;
    }

err_open:
    if(NULL != writeData)
    {
        free(writeData);
        writeData = NULL;
    }
err_malloc_writeData:

    if(NULL != data)
    {
        free(data);
        data = NULL;
    }
err_malloc:
    printf("[%s +%d %s] end ret=%d\n", __FILE__, __LINE__, __func__, ret);
    return ret;
}

static void show_uint8_content(uint8_t *data, uint32_t size)
{
    printf("show data :");
    for(int i = 0; i < size; i ++)
    {
        printf("%d ", data[i]);
    }
    printf("\n");
}